package com.liuwei.spring.cloud.common.utils;

import cn.hutool.core.util.IdUtil;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.deser.std.DateDeserializers;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.databind.module.SimpleModule;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;

/**
 * Jackson 默认使用 UTC 时间,工具类统一为系统当前时区
 * TimeZone.getDefault()
 */
@Slf4j
public class Jackson {
    /** 系统默认时区 */
    public static TimeZone TIMEZONE = TimeZone.getDefault();
    public static void main(String[] args) {
        Entity entity = new Entity();
        entity.setId(IdUtil.fastUUID());
        entity.setNow(new Date());

        SimpleDateFormat dateFormat  = new SimpleDateFormat(DateHelper.STANDARD_SECOND24);
        System.out.println(dateFormat.toPattern());
        System.out.println(Jackson.toJSONString(entity));
        String json = Jackson.toJSONString(entity,new SimpleDateFormat(DateHelper.STANDARD_SECOND24));

        Entity deserialize = Jackson.parseObject(json,Entity.class,dateFormat,true);
        System.out.println(Jackson.toJSONString(deserialize,new SimpleDateFormat(DateHelper.STANDARD_SECOND24)));
    }

    /** 系统默认时区 */


    @Data
    public static class Entity{
        private String id;

        //@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
        //@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
        Date now;
    }

    /**
     * 转换为 JSON 字符串
     * @param obj
     * @return
     * @throws Exception
     */
    public static String toJSONString(Object obj){
        ObjectMapper instance = new ObjectMapper();
        try {
            return instance.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            return null;
        }
    }

    public static String toJSONString(ObjectMapper instance,Object obj){
        try {
            return instance.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            return null;
        }
    }

    public static String toJSONString(Object obj,SimpleDateFormat dateFormat){
        ObjectMapper instance = new ObjectMapper();
        instance.setDateFormat(dateFormat);
        // 如果需要，禁用序列化特性
        // instance.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        instance.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        try {
            return instance.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 转换为 JSON 字符串，忽略空值
     *
     * @param obj
     * @return
     * @throws Exception
     */
    public static String toJSONStringIgnoreNull(Object obj){
        ObjectMapper instance = new ObjectMapper();
        instance.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        try {
            return instance.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 转换为 JavaBean
     *
     * @param jsonString
     * @param clazz
     * @return
     * @throws Exception
     */
    public static <T> T parseObject(String jsonString, Class<T> clazz,boolean ignoreUnkownField){
        ObjectMapper instance = new ObjectMapper();
        instance.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        instance.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
        instance.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, !ignoreUnkownField);
        try {
            return instance.readValue(jsonString, clazz);
        } catch (Exception e) {
            log.info("Jackson|反序列化异常:{}",e.getMessage(),e);
            throw new RuntimeException(e.getMessage());
        }
    }

    public static <T> T parseObject(String jsonString, Class<T> clazz, SimpleDateFormat dateFormat,boolean ignoreUnkownField){
        ObjectMapper instance = new ObjectMapper();
        // 设置默认的时间反序列化格式
        SimpleModule module = new SimpleModule();
        //module.addSerializer(Date.class, new DateSerializer(false,dateFormat));
        DateDeserializers.DateDeserializer base = new DateDeserializers.DateDeserializer();
        DateDeserializers.DateDeserializer dateDeserializerWithFormat = new DateDeserializers.DateDeserializer(base,dateFormat,dateFormat.toPattern());
        module.addDeserializer(Date.class, dateDeserializerWithFormat);
        //module.addDeserializer(Date.class, new DateDeserializers.TimestampDeserializer());
        //module.addDeserializer(Date.class, new DateDeserializers.SqlDateDeserializer());
        instance.registerModule(module);

        instance.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        instance.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
        instance.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, !ignoreUnkownField);
        try {
            return instance.readValue(jsonString, clazz);
        } catch (Exception e) {
            log.info("Jackson|反序列化异常:{}",e.getMessage(),e);
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * 字符串转换为 Map<String, Object>
     *
     * @param jsonString
     * @return
     * @throws Exception
     */
    public static <T> Map<String, T> parseMap(String jsonString){
        ObjectMapper instance = new ObjectMapper();
        instance.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        try {
            return instance.readValue(jsonString, new TypeReference<Map<String, T>>() {});
        } catch (Exception e) {
            log.info("Jackson|反序列化异常:{}",e.getMessage(),e);
            throw new RuntimeException(e.getMessage());
        }
    }

    public static <T> List<T> parseArray(String jsonString,Class<T> clazz){
        ObjectMapper instance = new ObjectMapper();
        instance.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        try {
            return instance.readValue(jsonString, instance.getTypeFactory().constructParametricType(List.class, clazz));
        } catch (Exception e) {
            log.info("Jackson|反序列化异常:{}",e.getMessage(),e);
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * Jackson Date 序列化方法
     */
    public static class DateFormatSerializer extends JsonSerializer<Date> {
        private SimpleDateFormat dateFormat;

        public DateFormatSerializer(String format) {
            super();
            dateFormat = new SimpleDateFormat(format);
        }

        @Override
        public void serialize(Date value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
            String formattedDate = dateFormat.format(value);
            gen.writeString(formattedDate);
        }
    }

    /**
     * Jackson Date 反序列化方法
     */
    public static class DateParserDeserializer extends StdDeserializer<Date> {
        private SimpleDateFormat dateFormat;

        public DateParserDeserializer(String format) {
            super(Date.class);
            dateFormat = new SimpleDateFormat(format);
        }

        @Override
        public Date deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
            String dateString = p.getText();
            try {
                //DateUtil.parse(dateString.trim());
                return dateFormat.parse(dateString);
            } catch (Exception e) {
                throw new IOException("Failed to parse date: " + dateString, e);
            }
        }
    }
}
